package com.qs.sckill.config.mvc;

import com.qs.sckill.entity.User;
import com.qs.sckill.service.UserService;
import com.qs.sckill.utils.CookieUtils;
import com.qs.sckill.utils.WebConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义参数解析器
 * 作用：获取cookie或者queryString中的token参数，并根据token获取到登录用户信息，将用户信息在每个请求中携带，
 * 请求中可以直接用User对象获取登录的用户对象；
 * @author qinyupeng
 * @since 2019-07-31 17:08:25
 */
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {

    @Resource
    private UserService userService;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> clazz = parameter.getParameterType();
        return clazz == User.class;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {

        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
        if (request == null || response == null) {
            return null;
        }

        //参数中是否携带token
        String paramToken = request.getParameter(WebConstants.COOKIE_NAME_TOKEN);
        //cookie中是否携带token
        String cookieToken = CookieUtils.getCookieValue(request, WebConstants.COOKIE_NAME_TOKEN);
        if (StringUtils.isBlank(cookieToken) && StringUtils.isEmpty(paramToken)) {
            return null;
        }

        //参数中token不存在，则使用cookie中token
        String token = StringUtils.isBlank(paramToken) ? cookieToken : paramToken;
        //返回已经登录的用户对象，未登录则返回null（user对象，在controller的方法中可以直接封装获取）
        return userService.getByToken(response, token);
    }
}
